#!/usr/bin/env python

class Material(object):
	def __init__(self, diffuse=None, emissive=None, transparency=None):
		self.diff = diffuse
		self.em = emissive
		self.transparent = transparency
		
	def set_diffuse(self, diffuse=None):
		self.diff = diffuse
		
	def set_emissive(self, emissive=None):
		self.em = emissive
		
	def set_transparency(self, transparency=None):
		self.transparent = transparency
		
	def diffuse(self):
		return self.diff
		
	def emissive(self):
		return self.em
		
	def transparency(self):
		return self.transparent

class Appearance(object):
	def __init__(self, material=None, texture=None):
		self.mat = material
		self.tex = texture
		
	def set_material(self, material=None):
		self.mat = material
		
	def set_texture(self, texture=None):
		self.tex = texture
		
	def material(self):
		return self.mat
		
	def texture(self):
		return self.tex
		
class FontStyle(object):
	def __init__(self, family=None, justify=None, style=None, size=None,
					spacing=None):
		self.fam = family
		self.just = justify
		self.style_ = style
		self.size_ = size
		self.space = spacing
		
	def set_family(self, family=None):
		self.fam = family
		
	def set_justify(self,justify=None):
		self.just = justify
		
	def set_style(self, style=None):
		self.style_ = style
		
	def set_size(self, size=None):
		self.size_ = size
		
	def set_spacing(self, spacing=None):
		self.space = spacing
		
	def family(self):
		return self.fam
		
	def justify(self):
		return self.just
		
	def style(self):
		return self.style_
	
	def size(self):
		return self.size_
		
	def spacing(self):
		return self.space

class Geometry(object):
	def __init__(self):
		pass
		
class Box(Geometry):
	def __init__(self, size=None, solid=None):
		self.size_ = size
		self.solid_ = solid
		
	def set_size(self, size=None):
		self.size_ = size
		
	def set_solid(self, solid=None):
		self.solid_ = solid
		
	def size(self):
		return self.size_
		
	def solid(self):
		return self.solid_
		
class Sphere(Geometry):
	def __init__(self, radius=None, solid=None):
		self.rad = radius
		self.solid_ = solid
		
	def set_radius(self, radius=None):
		self.rad = radius
		
	def set_solid(self, solid=None):
		self.solid_ = solid
		
	def radius(self):
		return self.rad
		
	def solid(self):
		return self.solid_
		
class Cylinder(Geometry):
	def __init__(self, radius=None, height=None, solid=None):
		self.rad = radius
		self.h = height
		self.solid_ = solid
		
	def set_radius(self, radius=None):
		self.rad = radius
		
	def set_height(self, height=None):
		self.h = height
		
	def set_solid(self, solid=None):
		self.solid_ = solid
		
	def radius(self):
		return self.rad
		
	def height(self):
		return self.h
		
	def solid(self):
		return self.solid_
		
class Text(Geometry):
	def __init__(self, strings=None, lengths=None, maxExtent=None, solid=None,
					fontStyle=None):
		self.strings_ = strings
		self.lengths_ = lengths
		self.maxExtent_ = maxExtent
		self.solid_ = solid
		self.fontStyle_ = fontStyle
		
	def set_strings_lengths(self, strings=None, lengths=None):
		self.strings_ = strings
		self.lengths_ = lengths
	
	def set_max_extent(self, maxExtent=None):
		self.maxExtent_ = maxExtent
		
	def set_solid(self, solid=None):
		self.solid_ = solid
		
	def set_font_style(self, fontStyle=None):
		self.fontStyle_ = fontStyle
		
	def strings(self):
		return self.strings_
	
	def lengths(self):
		return self.lengths_
	
	def max_extent(self):
		return self.maxExtent_
	
	def solid(self):
		return self.solid_
		
	def font_style(self):
		return self.fontStyle_
		
class LineSet(Geometry):
	def __init__(self, vertices=[], colors=[]):
		self.vertices_ = vertices
		self.colors_ = colors
		
	def append(self, vertex, color=None):
		self.vertices_.append(vertex)
		if self.colors_ and not color:
			raise RuntimeError("Must provide no colors or all colors")
		self.colors_.append(color)
		
	def vertices(self):
		return self.vertices_
		
	def colors(self):
		return self.colors_

class IndexedFaceSet(Geometry):
	def __init__(self, vertices=[], indices=[], colors=[]):
		self.vertices_ = vertices
		self.indices_ = indices
		self.colors_ = colors
		self.colorPerVertex_ = False

	def setColorPerVertex(self,value):
		self.colorPerVertex_ = value

	def setFaces(self, faces):
		self.indices_ = []
		for f in faces:
			self.indices_ += f
			self.indices_.append(-1)

	def setTriangles(self, indices):
		faces = [indices[i:i+3] for i in range(len(indices))[::3]]
		self.setFaces(faces)
		
	def appendFace(self, vertArray, color=None):
		ind0 = len(self._vertices)
		self.vertices_ += vertArray
		self.indices_ += range(ind0,ind0+len(vertices))
		self.indices_.append(-1)
		if self.colors_ and not color:
			raise RuntimeError("Must provide no colors or all colors")
		if self.colorPerVertex_:
			if isinstance(color,str):
				self.colors_ += [color]*len(vertArray)
			if len(color) == 3 and isinstance(color[0],(int,float)):
				self.colors_ += [color]*len(vertArray)
			else:
				if len(color) != len(vertArray):
					raise RuntimeError("Must provide each color for each vertex")
				self.colors_ += color
		else:
			self.colors_.append(color)
		
	def vertices(self):
		return self.vertices_

	def indices(self):
		return self.indices_
		
	def colors(self):
		return self.colors_

	def colorPerVertex(self):
		return self.colorPerVertex_

class SceneObj(object):
	def __init__(self):
		pass
		
class Group(SceneObj):
	def __init__(self):
		self.childs = []
	
	def append(self, child):
		self.childs.append(child)
		
	def extend(self, children):
		self.childs.extend(children)
		
	def remove(self, child):
		self.childs.remove(child)
	
	def children(self):
		return self.childs

class Transform(Group):
	def __init__(self, translate=None, rotate=None, scale=None, center=None,
					scaleOrientation=None):
		self.trans = translate
		self.rot = rotate
		self.scale_ = scale
		self.center_ = center
		self.scaleOrient = scaleOrientation
		Group.__init__(self)
		
	def set_translate(self, translate=None):
		self.trans = translate
		
	def set_rotate(self, rotate=None):
		self.rot = rotate
		
	def set_scale(self, scale=None):
		self.scale_ = scale
		
	def set_center(self, center=None):
		self.center_ = center
		
	def set_scale_orientation(self, scaleOrientation=None):
		self.scaleOrient = scaleOrientation
		
	def translate(self):
		return self.trans
		
	def rotate(self):
		return self.rot
		
	def scale(self):
		return self.scale_
		
	def center(self):
		return self.center_
		
	def scale_orientation(self):
		return self.scaleOrient

class Shape(SceneObj):
	def __init__(self, appearance=None, geometry=None):
		self.appear = appearance
		self.geom = geometry
		
	def set_appearance(self, appearance=None):
		self.appear = appearance
		
	def set_geometry(self, geometry=None):
		self.geom = geometry
		
	def appearance(self):
		return self.appear
	
	def geometry(self):
		return self.geom
		
class Bindable(SceneObj):
	def __init__(self, bind=False):
		self.bind_ = bind
		
	def set_bind(self, bind=False):
		self.bind_ = bind
	
	def bind(self):
		return self.bind_
		
class Viewpoint(Bindable):
	def __init__(self, bind=False, centerRotation=None, position=None,
					orientation=None, jump=None, fov=None):
		Bindable.__init__(self, bind)
		self.centerRot = centerRotation
		self.pos = position
		self.orient = orientation
		self.jump_ = jump
		self.field = fov
		
	def set_center_rotation(self, centerRotation=None):
		self.centerRot = centerRotation
		
	def set_position(self, position=None):
		self.pos = position
		
	def set_orientation(self, orientation=None):
		self.orient = orientation
		
	def set_jump(self, jump=None):
		self.jump_ = jump
		
	def set_fov(self, fov=None):
		self.field = fov
		
	def center_rotation(self):
		return self.centerRot
		
	def position(self):
		return self.pos
		
	def orientation(self):
		return self.orient
		
	def jump(self):
		return self.jump_
		
	def fov(self):
		return self.field

class Scene(object):
	def __init__(self):
		self.sceneObjs = []
		
	def append(self, obj):
		self.sceneObjs.append(obj)
		
	def clear(self):
		self.sceneObjs = []
		
	def remove(self, obj):
		self.sceneObjs.remove(obj)
		
	def objs(self):
		return self.sceneObjs
